<?php

/*
@版本日期: 2010年5月30日
@著作权所有: Lou Barnes ( http://www.loubarnes.com )

获得使用本类库的许可, 您必须保留著作权声明信息.
报告漏洞，意见或建议, 请联系 Lou Barnes(iua1024@gmail.com) 或登陆 http://www.loubarnes.com
*/

class lib_mail extends lib
{
    private $from_mail = null; // 发件邮箱
    private $from_name = null; // 发件人
    private $reply_to = null; // 接收回复邮箱
    private $to = array(); // 收件邮箱
    private $attachments = array(); // 附件
    

    private $subject = ''; // 邮件主题
    private $body = ''; // 邮件内容
    private $content_type = 'text/html'; // 邮件类型
    private $charset = "utf-8"; // 字符集
    

    private $smtp = null; // smtp 信息

    
    // 构造函数
    public function __construct()
    {
        $config = bone::get_config('mail');
        
        if ($config->from_mail) $this->from_mail = $config->from_mail;
        if ($config->from_name) $this->from_name = $config->from_name;
        if ($config->charset) $this->charset = $config->charset;
        if ($config->encoding) $this->encoding = $config->encoding;
        
        if ($config->smtp)
        {
            if (!$this->smtp) $this->smtp = new stdClass();
            $this->smtp->host = $config->smtp_host; // smtp 主机地址
            $this->smtp->user = $config->smtp_user; // smtp 用户名
            $this->smtp->pass = $config->smtp_pass; // smtp 用户密码
            $this->smtp->port = $config->smtp_port; // smtp 主机端口
            $this->smtp->ssl = $config->smtp_ssl; // smtp 用户密码
            $this->smtp->timeout = $config->smtp_timeout; // smtp 超时时间秒
        }
    }

    // 析构函数
    public function __destruct()
    {
    }

    public function set_from($from_mail, $from_name = null)
    {
        $this->from_mail = $from_mail;
        if ($from_name)
            $this->from_name = $from_name;
        else
            $this->from_name = $from_mail;
    }


    // 添加收件人
    public function to($email = null)
    {
        if ($this->verify($email))
        {
            $this->to[] = $email;
        }
        else
        {
            $this->set_error('邮箱(' . $email . ')格式非法');
            return false;
        }
        
        return true;
    }

    public function add_attachment($path = null)
    {
        // 暂未开发
        return;
    }

    public function set_subject($sSubject = '')
    {
        $this->subject = $sSubject;
    }

    public function set_body($body = '')
    {
        $this->body = $body;
    }

    public function send()
    {
        if (!count($this->to))
        {
            $this->set_error('未设置收件邮箱');
            return false;
        }
        
        if ($this->smtp)
        {
            return $this->smtp_send();
        }
        else
        {
            return mail(implode(", ", $this->to), $this->subject, $this->body, $this->create_header());
        }
    }

    public function smtp_send()
    {
        $socket = fsockopen($this->smtp->host, $this->smtp->port, $err_no, $err_msg, $this->smtp->timeout);
        if (!$socket)
        {
            $this->set_error('连接smtp主机(' . $this->smtp->host . ')失败: ' . $err_no . ' - ' . $err_msg);
            return false;
        }
        
        if (substr(PHP_OS, 0, 3) != "WIN") socket_set_timeout($socket, $this->smtp->timeout, 0);
        
        fputs($socket, 'HELO MrBone' . "\r\n");
        $line = trim(fgets($socket, 515));
        
        if ($this->smtp->user)
        {
            fputs($socket, "AUTH LOGIN\r\n");
            $line = trim(fgets($socket, 515));
            fputs($socket, base64_encode($this->smtp->user) . "\r\n");
            $line = trim(fgets($socket, 515));
            fputs($socket, base64_encode($this->smtp->pass) . "\r\n");
            $line = trim(fgets($socket, 515));
            $line = trim(fgets($socket, 515));
            $code = substr($line, 0, 3);
            if ($code != 235)
            {
                $this->set_error('smtp 用户名和密码验证错误: ' . $line);
                return false;
            }
        }
        fputs($socket, 'MAIL FROM:<' . $this->from_mail . ">\r\n");
        $line = trim(fgets($socket, 515));
        
        $to = $this->to;
        foreach ($to as $email)
        {
            fputs($socket, 'RCPT TO:<' . $email . ">\r\n");
            $line = trim(fgets($socket, 515));
        }
        fputs($socket, "DATA\r\n");
        $line = trim(fgets($socket, 515));
        
        $data = $this->create_header();
        $data .= $this->create_body();
        
        fputs($socket, $data);
        
        $line = trim(fgets($socket, 515));
        $code = substr($line, 0, 3);
        if ($code != 250)
        {
            $this->set_error('发送邮件失败: ' . $line);
            return false;
        }
        
        fputs($socket, "QUIT\r\n");
        return true;
    }

    public function reset()
    {
        $this->to = array();
        $this->attachments = array();
    }

    private function create_header()
    {
        $data = 'From: =?' . $this->charset . '?B?' . base64_encode($this->from_name) . '?= <' . $this->from_mail . ">\r\n";
        $data .= 'Reply-To: ' . $this->from_name . ' <' . $this->from_mail . ">\r\n";
        $data .= 'To: ' . implode(",", $this->to) . "\r\n";
        $data .= 'Subject: =?' . $this->charset . '?B?' . base64_encode($this->subject) . "?=\r\n";
        $data .= 'Message-ID: <' . time() . '.' . $this->from_mail . ">\r\n";
        $data .= 'Date: ' . date('r') . "\r\n";
        $data .= "X-Priority: 3\r\n";
        $data .= "X-Mailer: Mr Bone\r\n";
        $data .= "Copyright: www.mrbone.org\r\n";
        $data .= "MIME-Version: 1.0\r\n";
        $data .= 'Content-Type: ' . $this->content_type . '; charset="' . $this->charset . "\"\r\n\r\n";
        
        return $data;
    }

    private function create_body()
    {
        $data = $this->body . "\r\n.\r\n";
        return $data;
    }

    public function verify($email)
    {
        return preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/i", $email);
    }

}
